package com.ikingtech.framework.sdk.office.utils;


import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.ikingtech.framework.sdk.context.exception.FrameworkException;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.core.io.ClassPathResource;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;

/**
 * easyExcel 导入导出工具类
 *
 * @author yang
 */
public class ExcelUtil {


    private static final String EXECL_TEMPLATE_DIR = "excel-templates";

    public static final String TASK_TEMPLATE_NAME = "task.xlsx";

    /**
     * 获取模板文件路径
     *
     * @return String
     */
    public static InputStream getPath(String templateName) throws IOException {
        ClassPathResource classPathResource = new ClassPathResource("\\" + EXECL_TEMPLATE_DIR + "\\" + templateName);
        return classPathResource.getInputStream();
    }

    /**
     * 复杂单sheet页导出(采用模板方式导出,需要先配置对应模板)
     *
     * @param templateName 模板名称(需要带后缀文件格式)
     * @param fileName     文件名称
     * @param data         列表数据源
     * @param map          其他数据源
     * @param response     返回
     */
    public static void complexSingleSheetExport(String templateName, String fileName, List data, Map<Object, Object> map, HttpServletResponse response) {
        if (null == fileName || fileName.trim().isEmpty()) { //如果不设置文件名，则默认
            fileName = new String((templateName + LocalDate.now().format(DateTimeFormatter.ofPattern(("yyyy-MM-dd")))).getBytes(), StandardCharsets.UTF_8);
        }
        try (ExcelWriter excelWriter = EasyExcelFactory.write(response.getOutputStream()).registerConverter(new LocalDateConverter()).withTemplate(getPath(templateName)).build()) {
            WriteSheet writeSheet = EasyExcelFactory.writerSheet().build();
            // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行，然后下面的数据往后移动。默认 是false，会直接使用下一行，如果没有则创建。
            // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了，所以慎用
            // 简单的说 如果你的模板有list,且list不是最后一行，下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
            // 如果数据量大 list不是最后一行 参照下一个
//            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
            excelWriter.fill(data, writeSheet);
            excelWriter.fill(map, writeSheet);
        } catch (Exception e) {
            e.printStackTrace();
            throw new FrameworkException(e.getMessage());
        }

    }


    /**
     * 简单 单sheet页导出
     *
     * @param templateName 模板名称(需要带后缀文件格式)
     * @param fileName     文件名称
     * @param data         数据
     * @param response     返回
     */
    public static void simpleSingleSheetExport(String templateName, String fileName, List<T> data, HttpServletResponse response) {
        ExcelUtil.complexSingleSheetExport(templateName, fileName, data, null, response);
    }

    /**
     * 简单 单sheet页填充
     *
     * @param templateName 模板名称(需要带后缀文件格式)
     * @param data         数据
     */
    public static byte[] simpleSingleSheetFill(String templateName, List<T> data) {
        return ExcelUtil.complexSingleSheetFill(templateName, data, null);
    }

    /**
     * 复杂单sheet页数据填充(采用模板方式导出,需要先配置对应模板)
     *
     * @param templateName 模板名称(需要带后缀文件格式)
     * @param data         列表数据源
     * @param map          其他数据源
     */
    public static byte[] complexSingleSheetFill(String templateName, List data, Map<Object, Object> map) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try (
                ExcelWriter excelWriter = EasyExcelFactory.write(byteArrayOutputStream).registerConverter(new LocalDateConverter()).withTemplate(getPath(templateName)).build()) {
            WriteSheet writeSheet = EasyExcelFactory.writerSheet().build();
            // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行，然后下面的数据往后移动。默认 是false，会直接使用下一行，如果没有则创建。
            // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了，所以慎用
            // 简单的说 如果你的模板有list,且list不是最后一行，下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
            // 如果数据量大 list不是最后一行 参照下一个
//            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
            excelWriter.fill(data, writeSheet);
            excelWriter.fill(map, writeSheet);

        } catch (Exception e) {
            throw new FrameworkException(e.getMessage());
        }

        return byteArrayOutputStream.toByteArray();
    }

}
